﻿using System.Linq;
using CID.Domain.Infrastructure;
using CID.Tests.Support;
using NUnit.Framework;

namespace CID.Domain.Persistence.Tests.Infrastructure
{
    [TestFixture]
    class ParameterValuePersistenceTests : BasePersistenceWithDataTests
    {
        private static void AssertAreEqual(ParameterValue expected, ParameterValue actual)
        {
            Assert.AreEqual(expected.Id, actual.Id);
            Assert.AreEqual(expected.Definition.Id, actual.Definition.Id);
            Assert.AreEqual(expected.Parameter.Id, actual.Parameter.Id);
            Assert.AreEqual(expected.SerializedValue, actual.SerializedValue);
        }

        [Test]
        public void SaveNewParameterValue_ParameterValueShouldBeSaved()
        {
            var session = OpenSession();
            var newVersion = Development.DataProvider.GetVersion(session, DevelopmentData.Component1UnreleasedVersion);
            var deploymentDefinition = (DeploymentDefinition) newVersion.DeploymentDefinition;
            deploymentDefinition.DeploymentTemplate = DataProvider.GetTemplate<DeploymentTemplate>(session, InfrastructureData.DeploymentTemplate);
            var newParameterValue = (ParameterValue) deploymentDefinition.AddEnvironmentParameterValue(
                DataProvider.GetParameter(session, InfrastructureData.DeploymentTemplateUniqueIdentifierParameter), 
                Operations.DataProvider.GetEnvironment(session, OperationsData.Environment1));
            newParameterValue.UniqueIdentifierValue = System.Guid.NewGuid();
            session.SaveOrUpdate(newVersion);
            CleanSession(session);

            Assert.AreNotEqual(NotSavedId, newParameterValue.Id);
            session = OpenSession();
            var retrievedParameterValue = session.Get<ParameterValue>(newParameterValue.Id);
            AssertAreEqual(newParameterValue, retrievedParameterValue);
            CleanSession(session);
        }

        [Test]
        public void SaveModifiedParameterValue_ChangesShouldBeSaved()
        {
            var session = OpenSession();
            var newVersion = Development.DataProvider.GetVersion(session, DevelopmentData.Component1UnreleasedVersion);
            var deploymentDefinition = (DeploymentDefinition)newVersion.DeploymentDefinition;
            deploymentDefinition.DeploymentTemplate = DataProvider.GetTemplate<DeploymentTemplate>(session, InfrastructureData.DeploymentTemplate);
            var newParameterValue = (ParameterValue)deploymentDefinition.AddEnvironmentParameterValue(
                DataProvider.GetParameter(session, InfrastructureData.DeploymentTemplateUniqueIdentifierParameter),
                Operations.DataProvider.GetEnvironment(session, OperationsData.Environment1));
            newParameterValue.UniqueIdentifierValue = System.Guid.NewGuid();
            session.SaveOrUpdate(newVersion);
            CleanSession(session);

            session = OpenSession();
            var modifiedParameterValue = session.Get<ParameterValue>(newParameterValue.Id);
            AssertAreEqual(newParameterValue, modifiedParameterValue); //Necessary to load lazy collections before the session is wiped out
            modifiedParameterValue.UniqueIdentifierValue = System.Guid.NewGuid();
            session.SaveOrUpdate(modifiedParameterValue);
            CleanSession(session);

            session = OpenSession();
            var retrievedParameterValue = session.Get<ParameterValue>(newParameterValue.Id);
            AssertAreEqual(modifiedParameterValue, retrievedParameterValue);
            CleanSession(session);
        }

        [Test]
        public void DeleteParameterValue_ParameterValueShouldBeDeleted()
        {
            var session = OpenSession();
            var newVersion1 = Development.DataProvider.GetVersion(session, DevelopmentData.Component1UnreleasedVersion);
            var deploymentDefinition1 = (DeploymentDefinition)newVersion1.DeploymentDefinition;
            deploymentDefinition1.DeploymentTemplate = DataProvider.GetTemplate<DeploymentTemplate>(session, InfrastructureData.DeploymentTemplate);
            var newParameterValue1 = (ParameterValue)deploymentDefinition1.AddEnvironmentParameterValue(
                DataProvider.GetParameter(session, InfrastructureData.DeploymentTemplateUniqueIdentifierParameter),
                Operations.DataProvider.GetEnvironment(session, OperationsData.Environment1));
            newParameterValue1.UniqueIdentifierValue = System.Guid.NewGuid();
            session.SaveOrUpdate(newVersion1);
            var newVersion2 = Development.DataProvider.GetVersion(session, DevelopmentData.Component2UnreleasedVersion);
            var deploymentDefinition2 = (DeploymentDefinition)newVersion2.DeploymentDefinition;
            deploymentDefinition2.DeploymentTemplate = DataProvider.GetTemplate<DeploymentTemplate>(session, InfrastructureData.DeploymentTemplate);
            var newParameterValue2 = (ParameterValue)deploymentDefinition2.AddEnvironmentParameterValue(
                DataProvider.GetParameter(session, InfrastructureData.DeploymentTemplateUniqueIdentifierParameter),
                Operations.DataProvider.GetEnvironment(session, OperationsData.Environment1));
            newParameterValue2.UniqueIdentifierValue = System.Guid.NewGuid();
            session.SaveOrUpdate(newVersion2);
            CleanSession(session);

            session = OpenSession();
            var retrievedParameterValue1 = session.Get<ParameterValue>(newParameterValue1.Id);
            session.Delete(retrievedParameterValue1);
            CleanSession(session);

            session = OpenSession();
            retrievedParameterValue1 = session.Get<ParameterValue>(newParameterValue1.Id);
            var retrievedParameterValue2 = session.Get<ParameterValue>(newParameterValue2.Id);
            Assert.IsNull(retrievedParameterValue1);
            Assert.IsNotNull(retrievedParameterValue2);
            CleanSession(session);
        }
    }
}
